using System;
using System.Collections.Concurrent;
using System.Data;
using System.Data.OracleClient;
using System.Threading;
using System.Threading.Tasks;

namespace LTKJ.RTU
{
    /// <summary>
    /// 连接池管理器 - 优化数据库连接管理
    /// </summary>
    public class ConnectionPoolManager : IDisposable
    {
        private readonly ConcurrentQueue<OracleConnection> connectionPool;
        private readonly string connectionString;
        private readonly int maxPoolSize;
        private readonly int minPoolSize;
        private readonly SemaphoreSlim poolSemaphore;
        private volatile bool isDisposed = false;
        
        // 连接统计
        public int CurrentPoolSize => connectionPool.Count;
        public int MaxPoolSize => maxPoolSize;
        public int MinPoolSize => minPoolSize;
        
        // 事件
        public event Action<string> OnConnectionError;
        public event Action<string> OnPoolStatusChanged;
        
        public ConnectionPoolManager(string connectionString, int maxPoolSize = 20, int minPoolSize = 5)
        {
            this.connectionString = connectionString;
            this.maxPoolSize = maxPoolSize;
            this.minPoolSize = minPoolSize;
            
            connectionPool = new ConcurrentQueue<OracleConnection>();
            poolSemaphore = new SemaphoreSlim(maxPoolSize, maxPoolSize);
            
            // 初始化连接池
            InitializePool();
        }
        
        private void InitializePool()
        {
            try
            {
                for (int i = 0; i < minPoolSize; i++)
                {
                    var connection = CreateNewConnection();
                    if (connection != null)
                    {
                        connectionPool.Enqueue(connection);
                    }
                }
                
                OnPoolStatusChanged?.Invoke($"连接池初始化完成，当前连接数: {CurrentPoolSize}");
            }
            catch (Exception ex)
            {
                OnConnectionError?.Invoke($"连接池初始化失败: {ex.Message}");
            }
        }
        
        private OracleConnection CreateNewConnection()
        {
            try
            {
                var connection = new OracleConnection(connectionString);
                connection.Open();
                return connection;
            }
            catch (Exception ex)
            {
                OnConnectionError?.Invoke($"创建数据库连接失败: {ex.Message}");
                return null;
            }
        }
        
        /// <summary>
        /// 获取数据库连接
        /// </summary>
        public async Task<OracleConnection> GetConnectionAsync(CancellationToken cancellationToken = default)
        {
            if (isDisposed) throw new ObjectDisposedException(nameof(ConnectionPoolManager));
            
            try
            {
                // 等待可用连接
                await poolSemaphore.WaitAsync(cancellationToken);
                
                // 尝试从池中获取连接
                if (connectionPool.TryDequeue(out var connection))
                {
                    // 检查连接是否有效
                    if (IsConnectionValid(connection))
                    {
                        return connection;
                    }
                    else
                    {
                        // 连接无效，创建新连接
                        connection?.Dispose();
                        var newConnection = CreateNewConnection();
                        if (newConnection != null)
                        {
                            return newConnection;
                        }
                    }
                }
                
                // 池中没有可用连接，创建新连接
                var createdConnection = CreateNewConnection();
                if (createdConnection != null)
                {
                    return createdConnection;
                }
                
                // 如果创建失败，释放信号量并抛出异常
                poolSemaphore.Release();
                throw new InvalidOperationException("无法获取有效的数据库连接");
            }
            catch (Exception ex)
            {
                poolSemaphore.Release();
                OnConnectionError?.Invoke($"获取连接异常: {ex.Message}");
                throw;
            }
        }
        
        /// <summary>
        /// 释放连接回连接池
        /// </summary>
        public void ReleaseConnection(OracleConnection connection)
        {
            if (connection == null || isDisposed) return;
            
            try
            {
                // 检查连接是否仍然有效
                if (IsConnectionValid(connection))
                {
                    // 如果池未满，将连接放回池中
                    if (CurrentPoolSize < maxPoolSize)
                    {
                        connectionPool.Enqueue(connection);
                        OnPoolStatusChanged?.Invoke($"连接已释放回池，当前连接数: {CurrentPoolSize}");
                    }
                    else
                    {
                        // 池已满，关闭连接
                        connection.Close();
                        connection.Dispose();
                    }
                }
                else
                {
                    // 连接无效，关闭并创建新连接
                    connection.Close();
                    connection.Dispose();
                    
                    // 尝试创建新连接来维持最小连接数
                    if (CurrentPoolSize < minPoolSize)
                    {
                        var newConnection = CreateNewConnection();
                        if (newConnection != null)
                        {
                            connectionPool.Enqueue(newConnection);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                OnConnectionError?.Invoke($"释放连接异常: {ex.Message}");
                try
                {
                    connection?.Close();
                    connection?.Dispose();
                }
                catch { }
            }
            finally
            {
                // 释放信号量
                poolSemaphore.Release();
            }
        }
        
        /// <summary>
        /// 检查连接是否有效
        /// </summary>
        private bool IsConnectionValid(OracleConnection connection)
        {
            try
            {
                if (connection == null) return false;
                
                // 检查连接状态
                if (connection.State != ConnectionState.Open)
                    return false;
                
                // 尝试执行简单查询来验证连接
                using (var command = connection.CreateCommand())
                {
                    command.CommandText = "SELECT 1 FROM DUAL";
                    command.CommandType = CommandType.Text;
                    command.CommandTimeout = 5;
                    
                    var result = command.ExecuteScalar();
                    return result != null && result.ToString() == "1";
                }
            }
            catch
            {
                return false;
            }
        }
        
        /// <summary>
        /// 清理无效连接
        /// </summary>
        public void CleanupInvalidConnections()
        {
            try
            {
                var validConnections = new ConcurrentQueue<OracleConnection>();
                var removedCount = 0;
                
                while (connectionPool.TryDequeue(out var connection))
                {
                    if (IsConnectionValid(connection))
                    {
                        validConnections.Enqueue(connection);
                    }
                    else
                    {
                        connection?.Close();
                        connection?.Dispose();
                        removedCount++;
                    }
                }
                
                // 将有效连接放回池中
                while (validConnections.TryDequeue(out var validConnection))
                {
                    connectionPool.Enqueue(validConnection);
                }
                
                // 补充连接到最小数量
                while (CurrentPoolSize < minPoolSize)
                {
                    var newConnection = CreateNewConnection();
                    if (newConnection != null)
                    {
                        connectionPool.Enqueue(newConnection);
                    }
                    else
                    {
                        break;
                    }
                }
                
                if (removedCount > 0)
                {
                    OnPoolStatusChanged?.Invoke($"清理完成，移除 {removedCount} 个无效连接，当前连接数: {CurrentPoolSize}");
                }
            }
            catch (Exception ex)
            {
                OnConnectionError?.Invoke($"清理连接异常: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 获取连接池状态
        /// </summary>
        public ConnectionPoolStatus GetPoolStatus()
        {
            return new ConnectionPoolStatus
            {
                CurrentPoolSize = CurrentPoolSize,
                MaxPoolSize = maxPoolSize,
                MinPoolSize = minPoolSize,
                AvailableConnections = poolSemaphore.CurrentCount,
                Timestamp = DateTime.Now
            };
        }
        
        public void Dispose()
        {
            if (!isDisposed)
            {
                isDisposed = true;
                
                // 清理所有连接
                while (connectionPool.TryDequeue(out var connection))
                {
                    try
                    {
                        connection?.Close();
                        connection?.Dispose();
                    }
                    catch { }
                }
                
                // 释放信号量
                poolSemaphore?.Dispose();
                
                OnPoolStatusChanged?.Invoke("连接池已关闭");
            }
        }
    }
    
    /// <summary>
    /// 连接池状态
    /// </summary>
    public class ConnectionPoolStatus
    {
        public int CurrentPoolSize { get; set; }
        public int MaxPoolSize { get; set; }
        public int MinPoolSize { get; set; }
        public int AvailableConnections { get; set; }
        public DateTime Timestamp { get; set; }
    }
}
